package cn.alise.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import cn.alise.consts.BaseConsts;
import cn.alise.consts.ConfigConsts;
import cn.alise.exception.AuthorizationException;
import cn.alise.qdp.model.menu.Menu;
import cn.alise.qdp.model.user.User;
import cn.alise.qdp.service.admin.MenuService;
import cn.alise.qdp.service.user.UserService;
import cn.alise.util.JSONResult;

import com.alibaba.fastjson.JSONArray;

/**
 * 权限判断
 * @author CHENH
 */
@Service
public class AuthoriInterceptor extends HandlerInterceptorAdapter {
	
	@Autowired
	private MenuService menuService;
	
	@Autowired
	private UserService userService;
	
	/**
	 * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
	 *
	 * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链,
	 * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion()
	 *
	 * @throws Exception
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		
		if (menuService == null) {//解决service为null无法注入问题 
	        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); 
	        menuService = (MenuService) factory.getBean("menuService");
	    }
		
		if (userService == null) {//解决service为null无法注入问题 
	        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()); 
	        userService = (UserService) factory.getBean("userService");
	    }
		
		HttpSession session = request.getSession();
		if (session != null) {
			User account = (User) session.getAttribute(BaseConsts.IUser.USER_SESSION_KEY);
			if (account == null) {
				throw new AuthorizationException("登录session无效！");
			} else {
				// 判断是否需要经过权限判断
				JSONResult result = new JSONResult();
				String oldUrl = request.getRequestURI();
				String serverContextpath = ConfigConsts.SERVER_CONTEXTPATH + "/";
				String url = oldUrl.replace(serverContextpath, "");
				Menu args = new Menu();
				args.setDataHref(url);
				
				List<Menu> menuList = this.menuService.list(args);
				
				if (menuList.size()>0 && menuList.get(0).getType() == 2 && !"login/error404".equals(url)) {//结果不为空且类型为按钮，则需要经过权限判断，或者请求为login/error404的也不需要权限验证
					// 权限判断
					Long userId = account.getUserId();
					User user = new User();
					user.setUserId(userId);
					user.setDataHref(url);
					
					List<User> users = this.userService.authori(user);
					
					if(users.size() < 1) {//没有权限
						// 根据dataHref获取上级菜单的dataHref
						args.setDataHref(url);
						List<Menu> menu = this.menuService.getParentListByDataHref(args);
						
						if(menu.size()>0) {
							//判断是否为AJAX请求
							String requestType = request.getHeader("X-Requested-With");
							if(requestType!=null&&!"".equals(requestType)) {
								PrintWriter out = null;
								try {
									result.setMessage("没有操作权限！");
									result.setStatus(-1);
									// 得到输出流
									out = response.getWriter();
									out.print(JSONArray.toJSONString(result));
								} catch (IOException e) {
									e.printStackTrace();
								} finally {
									if (null != out) {
										out.flush();
										out.close();
									}
								}
							} else {
								request.setAttribute("_authoriError", "没有操作权限！");
								request.getRequestDispatcher("/"+menu.get(0).getDataHref()).forward(request,response);
							}
							return false;
						} else {
							throw new Exception();
						}
						
					} else {
						return true;
					}
				} else {//不经过权限判断
					return true;
				}
			}
		} else {
			throw new AuthorizationException("登录session无效！");
		}
	}
}